package com.mit.wx.service.impl;

import com.alibaba.fastjson.JSON;
import com.mit.wx.conf.WeixinConfiguration;
import com.mit.wx.dao.AdminDao;
import com.mit.wx.dao.BaseDao;
import com.mit.wx.dto.AdminDto;
import com.mit.wx.dto.WebAccessTokenDto;
import com.mit.wx.entity.Admin;
import com.mit.wx.service.AdminService;
import com.mit.wx.util.HttpUtil;
import com.mit.wx.util.QrCodeUtil;
import com.mit.wx.vo.WxLoginState;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Optional;

/**
 * 2018/10/20 Create by 郭文梁
 * AdminServiceImpl
 * 管理员业务服务实现
 *
 * @author 郭文梁
 * @date 2018/10/20
 */
@Service
public class AdminServiceImpl extends BaseServiceImpl<Admin> implements AdminService {
    private static final String ADMIN_BIND_OPEN_ID_QR_CODE_CONTENT_TEMPLATE
            = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect";
    private static final int ADMIN_BIND_OPEN_ID_QR_CODE_WIDTH = 200;
    private static final int ADMIN_BIND_OPEN_ID_QR_CODE_HEIGHT = 200;
    private static final String GET_ACCESS_TOKEN_URL =
            "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
    private final AdminDao adminDao;
    private final WeixinConfiguration weixinConfiguration;

    @Autowired
    public AdminServiceImpl(AdminDao adminDao, WeixinConfiguration weixinConfiguration) {
        this.adminDao = adminDao;
        this.weixinConfiguration = weixinConfiguration;
    }

    @Override
    public BaseDao<Admin> getRepository() {
        return adminDao;
    }

    @Override
    public AdminDto login(String name, String password) {
        Admin admin = adminDao.findByName(name);
        if (admin == null) {
            return null;
        }
        String pwd = DigestUtils.md5Hex(password);
        if (pwd.equalsIgnoreCase(admin.getPassword())) {
            AdminDto dto = AdminDto.of(admin);
            //不向前端传输密码信息
            dto.setPassword(null);
            return dto;
        }
        return null;
    }

    @Override
    public AdminDto findByName(String name) {
        Admin admin = adminDao.findByName(name);
        if (admin == null) {
            return null;
        }
        return AdminDto.of(admin);
    }

    @Override
    public AdminDto create(AdminDto adminDto) {
        Admin admin = new Admin();
        admin.setName(adminDto.getName());
        admin.setPassword(DigestUtils.md5Hex(adminDto.getPassword()));
        Admin result = save(admin);
        return AdminDto.of(result);
    }

    @Override
    public AdminDto findByOpenId(String openId) {
        Admin admin = adminDao.findByOpenId(openId);
        if (admin == null) {
            return null;
        }
        return AdminDto.of(admin);
    }

    @Override
    public AdminDto bindOpenId(Integer adminId, String openId) {
        Optional<Admin> admin = adminDao.findById(adminId);
        if (admin.isPresent()) {
            Admin entity = admin.get();
            entity.setOpenId(openId);
            Admin result = adminDao.save(entity);
            return AdminDto.of(result);
        } else {
            return null;
        }
    }

    @Override
    public AdminDto bindOpenIdByCode(Integer adminId, String code) {
        String url = String.format(GET_ACCESS_TOKEN_URL,
                weixinConfiguration.getAppID(),
                weixinConfiguration.getAppSecret(),
                code);
        try {
            String resp = HttpUtil.get(url);
            WebAccessTokenDto accessTokenDto = JSON.parseObject(resp, WebAccessTokenDto.class);
            if (accessTokenDto == null) {
                return null;
            }
            String openId = accessTokenDto.getOpenId();
            return bindOpenId(adminId, openId);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public byte[] getBindOpenIdQrCode(Integer adminId) {
        String targetUrl = weixinConfiguration.getBaseUrl() + "/admin-public/bind-open-id";
        WxLoginState state = new WxLoginState(adminId, null);
        String content = String.format(ADMIN_BIND_OPEN_ID_QR_CODE_CONTENT_TEMPLATE,
                weixinConfiguration.getAppID(),
                targetUrl,
                state.toBase64());
        return QrCodeUtil.encode(content, ADMIN_BIND_OPEN_ID_QR_CODE_WIDTH, ADMIN_BIND_OPEN_ID_QR_CODE_HEIGHT);
    }

    @Override
    public List<Admin> getBound() {
        return adminDao.findByOpenIdNotNull();
    }
}
